攻擊流程的本質: 攻擊者將惡意腳本注入到 Web 應用中,該腳本在受害者的瀏覽器上下文中執行,從而繞過了同源政策。XSS 的核心是「瀏覽器信任了來自伺服器的內容」,即使內容中包含了攻擊者注入的惡意部分。
三種類型的技術區分:
第一部分:XSS 的核心本質——信任的濫用
XSS 的根本原因並非伺服器被駭,而是瀏覽器在渲染網頁時,錯誤地執行了由攻擊者提供的惡意腳本 (Script)。
整個攻擊的核心在於,瀏覽器無法分辨一段腳本是由網站開發者所寫,還是由惡意攻擊者注入的。只要腳本出現在網頁的 HTML 內容中,瀏覽器就會一視同仁地執行它。因此,XSS 的攻擊目標是網站的其他用戶,而非網站伺服器本身。攻擊者利用受害者對目標網站的信任,來執行非預期的操作。
第二部分:XSS 的三種類型——技術的深度剖析
理解這三種類型的底層差異,是精通 XSS 的關鍵。
攻擊流程:
攻擊者構造一個包含惡意 JavaScript 的 URL。例如:
http://example.com/search?query=alert('XSS')
攻擊者透過社交工程、釣魚郵件等方式,誘騙受害者點擊這個惡意 URL。
受害者的瀏覽器向 example.com 發送請求。
伺服器從 query 參數中獲取 alert('XSS'),並將其直接嵌入到搜尋結果頁面的 HTML 中,例如:
受害者的瀏覽器接收到回應後,解析 HTML 並執行其中的惡意腳本。
關鍵特點:
非持久性: 攻擊 payload 不會被儲存在伺服器上。
需要互動: 必須誘騙用戶點擊特製的連結才能觸發。
攻擊流程:
攻擊者在網站上尋找一個可以提交數據並被儲存的地方,例如:用戶評論區、文章發表、個人資料設定等。
攻擊者提交一段包含惡意 JavaScript 的內容,例如:
這是一篇很棒的文章!
伺服器未經驗證和編碼,將這段內容儲存到資料庫中。
任何其他用戶(受害者)瀏覽包含這條惡意評論的頁面。
伺服器從資料庫中讀取惡意內容,並將其嵌入到 HTML 頁面中。
所有瀏覽此頁面的受害者的瀏覽器,都會執行這段惡意腳本。
關鍵特點:
持久性: 攻擊 payload 被儲存在伺服器上。
無需互動: 只要用戶瀏覽被污染的頁面,就會自動觸發攻擊,形成「XSS 蠕蟲」的潛力。
攻擊流程:
網站的前端 JavaScript 代碼,會從某個來源(通常是 URL 片段 #)獲取數據,並在未經處理的情況下,使用它來動態修改頁面的 DOM (文件物件模型)。
攻擊者構造一個惡意 URL,例如:
http://example.com/page.html#<img src=1 onerror=alert('DOM-XSS')>
受害者點擊此 URL。瀏覽器向 example.com 請求 page.html。注意,URL 片段 (# 後的內容) 不會被發送到伺服器。
page.html 中可能有一段不安全的 JavaScript 代碼,例如:
這段腳本獲取了 # 後的 標籤,並將其寫入到頁面的 content 元素中。瀏覽器在渲染這個新元素時,會因為 src=1 載入失敗而觸發 onerror 事件,執行其中的惡意腳本。
關鍵特點:
客戶端漏洞: 漏洞存在於前端 JavaScript 代碼中,與後端無關。
伺服器無感知: 惡意 payload 可能永遠不會到達伺服器日誌。
第三部分:XSS 的真實利用——超越 alert(1) 的威力
alert(1) 只是用來證明漏洞存在的概念驗證 (PoC)。在真實世界中,攻擊者會利用 XSS 執行極具破壞性的攻擊:
會話劫持 (Session Hijacking): 這是最核心的威脅。攻擊者注入的腳本可以讀取受害者的 document.cookie,並將其發送到攻擊者控制的伺服器。一旦攻擊者獲得了包含會話 ID 的 Cookie,他就可以將其設定在自己的瀏覽器中,完全冒充受害者登入系統,執行受害者能執行的所有操作。
鍵盤側錄 (Keylogging): 攻擊者可以注入一個鍵盤事件監聽器 (addEventListener('keydown', ...)), 記錄用戶在頁面上(特別是登入表單、密碼框中)輸入的所有內容,並將其發送到遠端伺服器。
介面偽造與釣魚 (UI Redressing & Phishing): 攻擊者可以利用 JavaScript 完全改變頁面的外觀,例如,在一個受信任的網頁上,動態插入一個偽造的登入框,並提示用戶「您的會話已過期,請重新登入」。用戶輸入的憑證將被直接發送給攻擊者。
瀏覽器漏洞利用 (Browser Exploitation): 攻擊者可以利用 XSS 作為跳板,引入更複雜的攻擊框架(如 BeEF - The Browser Exploitation Framework)。一旦受害者的瀏覽器被「鉤住」(hooked),攻擊者就可以像操作木馬一樣遠端控制瀏覽器,發動內網掃描、觸發瀏覽器漏洞等。
繞過 CSRF 防護: 如果一個網站使用了 Anti-CSRF Token 來防禦跨站請求偽造,攻擊者可以利用 XSS 漏洞,先用 AJAX 請求獲取包含 Token 的頁面,從中解析出 Token,然後再用這個 Token 構造出合法的 CSRF 請求。
第四部分:XSS 的縱深防禦——工程化的解決方案
防禦 XSS 不是單靠一個 filter() 函數就能解決的,它需要一個多層次、系統性的防禦策略。
插入到 HTML 元素內容中 (HTML Body Context):
場景: [USER_INPUT]
策略: HTML 實體編碼 (HTML Entity Encoding)。將特殊字元轉換為 HTML 實體。
< -> <
-> >
& -> &
" -> "
' -> '
插入到 HTML 屬性中 (HTML Attribute Context):
場景:
策略: 屬性編碼。除了上述 HTML 實體編碼,還應對除字母和數字外的所有字元使用 &#xHH; 格式進行編碼。
插入到 JavaScript 變數中 (JavaScript Context):
場景: var username = '[USER_INPUT]';
策略: JavaScript Unicode 轉義。將非字母數字的字元轉換為 \uXXXX 格式,以防止用戶輸入 '; alert(1); // 這樣的內容來閉合引號並注入新指令。
插入到 URL 中 (URL Context):
場景:
策略: URL 編碼 (Percent Encoding)。
一個嚴格的 CSP 策略可以極大地緩解 XSS 帶來的危害,即使漏洞仍然存在。例如:
Content-Security-Policy: default-src 'self'; script-src 'self' static.example.com;
這個策略表示:預設只信任同源內容;對於腳本,只信任同源 (self) 和 static.example.com 這兩個來源。這將直接禁止所有內聯腳本 (inline script) 和 eval() 的執行,讓許多 XSS payload 失效。
使用 HttpOnly Cookie 屬性: 為你的會話 Cookie 設置 HttpOnly 標誌。這樣一來,即使存在 XSS 漏洞,攻擊者的 JavaScript 也無法透過 document.cookie 讀取到會話 Cookie,有效防禦了最直接的會話劫持攻擊。
利用現代前端框架: 像 React, Angular, Vue 等現代框架,在設計上就內置了 XSS 防護。例如,它們在渲染數據時會預設進行輸出編碼。但開發者仍然需要小心,避免使用 dangerouslySetInnerHTML (React) 或 v-html (Vue) 等會繞過這些安全機制的危險功能
縱深防禦-內容安全策略 (CSP): CSP 是一個 HTTP 回應標頭,它允許網站管理員定義一個「白名單」,明確告知瀏覽器哪些來源的腳本、樣式、圖片等資源是允許載入和執行的。一個嚴格的 CSP 可以極大地緩解即使存在 XSS 注入點時的實際危害。